package controller

import (
	"encoding/json"
	"fabric-explorer/tools"
	"fmt"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

const (
	CHAINCODE_SPECTRUM = "spectrum"
)

//基站
type PU struct {
	Id   string `json:"id"`
	Idle bool   `json:"idle"`
}

//传感器
type Sensor struct {
	Address    string  `json:"address"`    //地址
	TrustValue float64 `json:"trustValue"` //信任值  0-1
	Deposit    float64 `json:"deposit"`    //存款
	MsgId      string  `json:"msgId"`
	LocationX  float64 `json:"locationX"` //坐标x
	LocationY  float64 `json:"locationY"` //坐标y
	Timestamp  int64   `json:"timestamp"` //时间戳
	SR         string  `json:"SR"`
	Msg        string  `json:"msg"`  //探测结果
	RSIG       string  `json:"RSIG"` //环签名
}

//投标者
type Bidder struct {
	BidderId string  `json:"bidderId"`
	Deposit  float64 `json:"deposit"`
}

//协作感知合约（CSC）
type CSC struct {
	Id             string    `json:"id"`
	SACId          string    `json:"SACId"`
	Deadline       time.Time `json:"deadline"`       //结束时间Tddl
	Deposit        float64   `json:"deposit"`        //定金ds
	MaxNum         int       `json:"maxNum"`         //支持的最大传感器数量N1
	MiniTtustValue float64   `json:"miniTtustValue"` //参与的最小信任值TVthr
	SensorNum      int       `json:"sensorNum"`      //传感器数量
	SensorList     []Sensor  `json:"sensorList"`     //参与的传感器
	MsgList        []string  `json:"msgList"`        //探测结果集合
	Result         string    `json:"result"`         //探测结果
}

//频谱拍卖合约（SAC）
type SAC struct {
	Id         string             `json:"id"`
	CSCId      string             `json:"CSCId"`      //表示CSC的id
	MaxNum     int                `json:"maxNum"`     //支持的最大投标者N2
	Deadline   time.Time          `json:"deadline"`   //结束时间Tself-d
	MiniTokens float64            `json:"miniTokens"` //竞标者需要投入的代币量da
	DpsMap     map[string]float64 `json:"dpsMap"`     //DpsMap记录投标者id和投出的总额
	Winner     string             `json:"winner"`     //获胜者
	Refund     float64            `json:"refund"`
}

type TableRow struct {
	Id         string  `json:"id"`
	Type       string  `json:"type"`
	TrustValue string  `json:"trustValue"`
	Status     string  `json:"status"`
	Deposit    float64 `json:"deposit"`
}

//spectrum链码 QueryPUList
func SpectrumQueryPUList(c *gin.Context) {
	result, err := tools.QueryChaincode(CHAINCODE_SPECTRUM, "QueryPUList")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	PUList := []PU{}
	json.Unmarshal(result, &PUList)
	tools.SuccessResult(c, PUList)
}

//spectrum链码 QuerySensorList
func SpectrumQuerySensorList(c *gin.Context) {
	result, err := tools.QueryChaincode(CHAINCODE_SPECTRUM, "QuerySensorList")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	sensorList := []Sensor{}
	json.Unmarshal(result, &sensorList)
	tools.SuccessResult(c, sensorList)
}

//spectrum链码 QueryBidderList
func SpectrumQueryBidderList(c *gin.Context) {
	result, err := tools.QueryChaincode(CHAINCODE_SPECTRUM, "QueryBidderList")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	bidderList := []Bidder{}
	json.Unmarshal(result, &bidderList)
	tools.SuccessResult(c, bidderList)
}

//spectrum链码 查询基本的参与者
func SpectrumQueryPUSensorBidderList(c *gin.Context) {
	result, err := tools.QueryChaincode(CHAINCODE_SPECTRUM, "QueryPUList")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	PUList := []PU{}
	json.Unmarshal(result, &PUList)
	result, err = tools.QueryChaincode(CHAINCODE_SPECTRUM, "QuerySensorList")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	sensorList := []Sensor{}
	json.Unmarshal(result, &sensorList)
	result, err = tools.QueryChaincode(CHAINCODE_SPECTRUM, "QueryBidderList")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	bidderList := []Bidder{}
	json.Unmarshal(result, &bidderList)
	tableRowList := make([]TableRow, 0)
	for _, p := range PUList {
		status := "idle"
		if !p.Idle {
			status = "busy"
		}
		t := TableRow{
			Id:         p.Id,
			Type:       "PU",
			TrustValue: "1",
			Status:     status,
		}
		tableRowList = append(tableRowList, t)
	}
	for _, s := range sensorList {
		t := TableRow{
			Id:         s.Address,
			Type:       "Sensor",
			TrustValue: strconv.FormatFloat(s.TrustValue, 'f', 2, 64),
			Status:     "idle",
		}
		tableRowList = append(tableRowList, t)
	}
	for _, b := range bidderList {
		t := TableRow{
			Id:         b.BidderId,
			TrustValue: "1",
			Type:       "Bidder",
			Status:     "idle",
			Deposit:    b.Deposit,
		}
		tableRowList = append(tableRowList, t)
	}
	tools.SuccessResult(c, tableRowList)
}

//spectrum链码 CreateCSCAndSAC
func SpectrumCreateCSCAndSAC(c *gin.Context) {
	result, err := tools.ExecuteChaincode(CHAINCODE_SPECTRUM, "CreateCSCAndSAC")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	resultMap := make(map[string]interface{})
	json.Unmarshal(result, &resultMap)
	fmt.Printf("resultMap: %v\n", resultMap)
	tools.SuccessResult(c, resultMap)
}

//spectrum链码 Fusion
func SpectrumFusion(c *gin.Context) {
	cscId := c.Query("cscId")
	if cscId == "" {
		tools.FailResult(c, "chaincode<spectrum> Fusion paras invalid")
		return
	}
	result, err := tools.ExecuteChaincode(CHAINCODE_SPECTRUM, "Fusion", cscId)
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	csc := CSC{}
	json.Unmarshal(result, &csc)
	tools.SuccessResult(c, csc)
}

//spectrum链码 Commit
func SpectrumCommit(c *gin.Context) {
	sacId := c.Query("sacId")
	bidderId := c.Query("bidderId")
	if sacId == "" || bidderId == "" {
		tools.FailResult(c, "chaincode<spectrum> Commit paras invalid")
		return
	}
	result, err := tools.ExecuteChaincode(CHAINCODE_SPECTRUM, "Commit", sacId, bidderId)
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	tools.SuccessResult(c, result)
}

//spectrum链码 Reveal
func SpectrumReveal(c *gin.Context) {
	sacId := c.Query("sacId")
	if sacId == "" {
		tools.FailResult(c, "chaincode<spectrum> Reveal paras invalid")
		return
	}
	result, err := tools.ExecuteChaincode(CHAINCODE_SPECTRUM, "Reveal", sacId)
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	tools.SuccessResult(c, result)
}

//spectrum链码 DeleteLedgerData，InitLedgerData
func SpectrumReset(c *gin.Context) {
	_, err := tools.ExecuteChaincode(CHAINCODE_SPECTRUM, "DeleteLedgerData")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	result, err := tools.ExecuteChaincode(CHAINCODE_SPECTRUM, "InitLedgerData")
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	tools.SuccessResult(c, result)
}

//spectrum链码 GetCSCById
func SpectrumGetCSCById(c *gin.Context) {
	cscId := c.Query("cscId")
	if cscId == "" {
		tools.FailResult(c, "chaincode<spectrum> GetCSCById paras invalid")
		return
	}
	result, err := tools.QueryChaincode(CHAINCODE_SPECTRUM, "GetCSCById", cscId)
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	cas := CSC{}
	json.Unmarshal(result, &cas)
	tools.SuccessResult(c, cas)
}

//spectrum链码 GetSACById
func SpectrumGetSACById(c *gin.Context) {
	sacId := c.Query("sacId")
	if sacId == "" {
		tools.FailResult(c, "chaincode<spectrum> GetSACById paras invalid")
		return
	}
	result, err := tools.QueryChaincode(CHAINCODE_SPECTRUM, "GetSACById", sacId)
	if err != nil {
		tools.FailResult(c, err.Error())
		return
	}
	sac := SAC{}
	json.Unmarshal(result, &sac)
	tools.SuccessResult(c, sac)
}
